/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package weka.attributeSelection.semiAS.semiClusterAS;

/**
 *
 * @author Administrator
 */
public class HierarchicalForSemiAS extends ClusterForSemiAS {

    public HierarchicalForSemiAS(int[] indicator, double[][] distance, int numAttribs, int numCluster) {
        super(indicator, distance, numAttribs, numCluster);
    }
    public void run() {
        for (int i = 1; i < m_numAttribs; i++) {
            m_indicator[i - 1] = i;
        }
        int curNumCluster = m_numAttribs - 1;
        double[][] curDistance = m_distance.clone();
        while (curNumCluster != m_numCluster) {            //未达到聚类数要求时循环迭代进行聚类
            double min_dis = curDistance[0][1];
            int min_i = 1;
            int min_j = 0;
            for (int i = 0; i < curNumCluster; i++) {      //找出距离最近的两个聚类
                for (int j = 0; j < i; j++) {
                    if (curDistance[i][j] < min_dis) {
                        min_dis = curDistance[i][j];
                        min_i = i;
                        min_j = j;
                    }
                }
            }
            int preNumCluster = curNumCluster;
            curNumCluster--;                               //合并聚类，使聚类数减1
            double[][] preDistance = curDistance.clone();
            curDistance = new double[curNumCluster][curNumCluster];   //更新距离矩阵

            int k = 0;
            int q = 0;
            int[] preIndicator = m_indicator.clone();
            for (int i = 0; i < preNumCluster; i++) {
                {
                    if (i != min_i && i != min_j) {
                        for (int j = 0; j < preNumCluster; j++) {
                            if (j != min_i && j != min_j) {//剩余未选中聚类距离直接赋值到相应的新距离矩阵
                                int ii = k / (curNumCluster - 1) + 1;
                                int jj = k % (curNumCluster - 1) + 1;
                                k++;
                                curDistance[ii][jj] = preDistance[i][j];

                                for (int a = 0; a < m_numAttribs - 1; a++) {//更新聚类指示器
                                    if (preIndicator[a] == i + 1) {
                                        m_indicator[a] = ii + 1;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            int n1 = numCluster(min_i + 1, preIndicator);
            int n2 = numCluster(min_j + 1, preIndicator);
            int n12 = n1 + n2;
            for (int i = 0; i < preNumCluster; i++) {//采用Ward最小方差法重新计算新合并聚类距离并赋给新距离矩阵的0行和0列
                if (i != min_i && i != min_j) {
                    q++;

                    double d = n1 * 1.0 / n12 * preDistance[min_i][i] + n2 * 1.0 / n12 * preDistance[min_j][i] - n1 * n2 * 1.0 / n12 * n12 * preDistance[min_i][min_j];
                    d = n1 * n2 * 1.0 / n12 * d;
                    //curDistance[0][q] = curDistance[q][0] = (preDistance[min_i][i] + preDistance[min_j][i]) * 0.5;
                    curDistance[0][q] = curDistance[q][0] = d;
                }
            }

            for (int a = 0; a < m_numAttribs - 1; a++) {//更新聚类指示器,新合并聚类的聚类号为1
                if (preIndicator[a] == min_i + 1 || preIndicator[a] == min_j + 1) {
                    m_indicator[a] = 1;
                }
            }
        }
    }

        private int numCluster(int c, int[] p) {
        int n = 0;
        for (int i = 0; i < p.length; i++) {
            if (p[i] == c) {
                n++;
            }
        }
        return n;
    }
}
